import { user } from './resource/user'
import { information } from './resource/information'
import { article } from './resource/article'
import { discuss } from './resource/discuss'
import { news } from './resource/news'

const zoneName = "devForum"
const clouddb = require('@hw-agconnect/database-server/dist/index.js')
const agconnect = require('@hw-agconnect/common-server')
const path = require('path');
const credentialPath = "/resource/agc-apiclient-1341328693062035136-7328025712296950955.json"
let mCloudDBZone

class CloudDbUtils {
  constructor(log) {
    let agcClient
    try {
      agcClient = agconnect.AGCClient.getInstance()
    } catch (error) {
      agconnect.AGCClient.initialize(agconnect.CredentialParser.toCredential(path.join(__dirname, credentialPath)));
      agcClient = agconnect.AGCClient.getInstance()
    }
    clouddb.AGConnectCloudDB.initialize(agcClient)
    const cloudDBZoneConfig = new clouddb.CloudDBZoneConfig(zoneName)
    const agconnectCloudDB = clouddb.AGConnectCloudDB.getInstance(agcClient)
    mCloudDBZone = agconnectCloudDB.openCloudDBZone(cloudDBZoneConfig)
    log.info('Cloud DB init successfully')
  }

  async queryUser(uid: string) {
    if (!mCloudDBZone) {
      console.log("CloudDB Client is null, try re-initialize it");
      return;
    }
    try {
      let resp = await mCloudDBZone.executeQuery(clouddb.CloudDBZoneQuery.where(user).equalTo('uid', uid))
      return resp.getSnapshotObjects()
    } catch (error) {
      console.error(JSON.stringify(error))
    }
  }

  async queryNews() {
    if (!mCloudDBZone) {
      console.log("CloudDB Client is null, try re-initialize it");
      return;
    }
    try {
      let resp = await mCloudDBZone.executeQuery(clouddb.CloudDBZoneQuery.where(news).orderByDesc("id"))
      console.info(`info :${JSON.stringify(resp)}`)
      return resp.getSnapshotObjects()
    } catch (error) {
      console.error(JSON.stringify(error))
    }
  }

  async queryDiscuss(article_id: number) {
    if (!mCloudDBZone) {
      console.log("CloudDB Client is null, try re-initialize it");
      return;
    }
    try {
      let resp = await mCloudDBZone.executeQuery(clouddb.CloudDBZoneQuery.where(discuss).equalTo('article_id', article_id))
      let discussList: Array<discuss> = resp.getSnapshotObjects()
      for (let index = 0; index < discussList.length; index++) {
        let user: user = (await this.queryUser(discussList[index].uid))[0]
        discussList[index].setPortrait(user.getPortrait())
      }
      console.info(`${JSON.stringify(discussList)}`)
      return discussList
    } catch (error) {
      console.error(JSON.stringify(error))
    }
  }

  async queryArticles(type: string) {
    if (!mCloudDBZone) {
      console.log("CloudDB Client is null, try re-initialize it");
      return;
    }
    try {
      let articleList
      if ('全部' === type) {
        articleList = await mCloudDBZone.executeQuery(clouddb.CloudDBZoneQuery.where(article).orderByDesc("id"))
      } else {
        articleList = await mCloudDBZone.executeQuery(clouddb.CloudDBZoneQuery.where(article).equalTo('type', type).orderByDesc("id"))
      }
      return articleList.getSnapshotObjects()
    } catch (error) {
      console.error(JSON.stringify(error))
    }
  }

  async queryArticlesBySearchContent(searchContent: string) {
    if (!mCloudDBZone) {
      console.log("CloudDB Client is null, try re-initialize it");
      return;
    }
    try {
      let resp = await mCloudDBZone.executeQuery(clouddb.CloudDBZoneQuery.where(article).orderByDesc("id"))
      const rExp: RegExp = new RegExp(searchContent)
      let articleList: Array<article> = resp.getSnapshotObjects()
      let articleArray: Array<article> = []
      for (let article of articleList) {
        if (rExp.test(article.getMain_body())) {
          articleArray.push(article)
        }
      }
      return articleArray
    } catch (error) {
      console.error(JSON.stringify(error))
    }
  }

  async queryArticlesByUid(uid: string) {
    if (!mCloudDBZone) {
      console.log("CloudDB Client is null, try re-initialize it");
      return;
    }
    try {
      let resp = await mCloudDBZone.executeQuery(clouddb.CloudDBZoneQuery.where(article).equalTo('uid', uid).orderByDesc("id"))
      return resp.getSnapshotObjects()
    } catch (error) {
      console.error(JSON.stringify(error))
    }
  }

  async queryInformation() {
    if (!mCloudDBZone) {
      console.log("CloudDB Client is null, try re-initialize it");
      return;
    }
    try {
      let info = await mCloudDBZone.executeQuery(clouddb.CloudDBZoneQuery.where(information).orderByDesc("id"))
      return info.getSnapshotObjects()
    } catch (error) {
      console.error(JSON.stringify(error))
    }
  }

  async updateUpvote(id: number, uid: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    const article = clouddb.CloudDBZoneGenericObject.build('article');
    const user = clouddb.CloudDBZoneGenericObject.build('user');
    article.addFieldValue('id', id, true);
    user.addFieldValue('uid', uid, true);
    try {
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(article).increment('upvote', 1));
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).increment('total_upvote', 1));
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).increment('integral', 20));
    } catch (error) {
      console.warn('upvote article error=>', error)
    }
  }

  async updatePortrait(uid: string, portrait: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    const user = clouddb.CloudDBZoneGenericObject.build('user');
    user.addFieldValue('uid', uid, true);
    try {
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).update('portrait', portrait));
    } catch (error) {
      console.warn('update portrait error=>', error)
    }
  }

  async updateName(uid: string, name: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    const user = clouddb.CloudDBZoneGenericObject.build('user');
    user.addFieldValue('uid', uid, true);
    try {
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).update('name', name));
    } catch (error) {
      console.warn('update portrait error=>', error)
    }
  }

  async updateIntroduce(uid: string, introduce: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    const user = clouddb.CloudDBZoneGenericObject.build('user');
    user.addFieldValue('uid', uid, true);
    try {
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).update('introduce', introduce));
    } catch (error) {
      console.warn('update portrait error=>', error)
    }
  }

  async unUpdateUpvote(id: number, uid: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    const article = clouddb.CloudDBZoneGenericObject.build('article');
    const user = clouddb.CloudDBZoneGenericObject.build('user');
    article.addFieldValue('id', id, true);
    user.addFieldValue('uid', uid, true);
    try {
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(article).increment('upvote', -1));
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).increment('total_upvote', -1));
    } catch (error) {
      console.warn('upvote article error=>', error)
    }
  }

  async updateReading(id: number, uid: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    const article = clouddb.CloudDBZoneGenericObject.build('article');
    const user = clouddb.CloudDBZoneGenericObject.build('user');
    article.addFieldValue('id', id, true);
    user.addFieldValue('uid', uid, true);
    try {
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(article).increment('reading', 1));
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).increment('total_reading', 1));
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).increment('integral', 10));
    } catch (error) {
      console.warn('upvote article error=>', error)
    }
  }


  async insertUser(uid: string, name: string, phone: string, email: string, career: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    try {
      const user = clouddb.CloudDBZoneGenericObject.build('user');
      user.addFieldValue('uid', uid, true);
      user.addFieldValue('name', name);
      user.addFieldValue('phone', phone);
      user.addFieldValue('email', email);
      user.addFieldValue('career', career);
      await mCloudDBZone.executeUpsert(user);
    } catch (error) {
      console.warn('upsertUserInfo =>', error)
    }
  }

  async insertDiscuss(uid: string, article_id: number, date: Date, name: string, main_body: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    try {
      const discuss = clouddb.CloudDBZoneGenericObject.build('discuss');
      discuss.addFieldValue('uid', uid);
      discuss.addFieldValue('name', name);
      discuss.addFieldValue('article_id', article_id);
      discuss.addFieldValue('date', date);
      discuss.addFieldValue('main_body', main_body);
      await mCloudDBZone.executeUpsert(discuss);
    } catch (error) {
      console.warn('upsertUserInfo =>', error)
    }
  }

  async insertArticle(uid: string, title: string, ip_address: string, date: Date, main_body: string, type: string) {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    try {
      const article = clouddb.CloudDBZoneGenericObject.build('article');
      const user = clouddb.CloudDBZoneGenericObject.build('user');
      user.addFieldValue('uid', uid, true);
      article.addFieldValue('uid', uid);
      article.addFieldValue('title', title);
      article.addFieldValue('date', date);
      article.addFieldValue('main_body', main_body);
      article.addFieldValue('ip_address', ip_address);
      article.addFieldValue('type', type);
      await mCloudDBZone.executeUpsert(article);
      await mCloudDBZone.executeUpdate(clouddb.CloudDBZoneObjectOperator.build(user).increment('integral', 40));
    } catch (error) {
      console.warn('upsertArticleInfo =>', error)
    }
  }

  async deleteArticle(id: number) {
    if (!mCloudDBZone) {
      console.log("CloudDB Client is null, try re-initialize it");
      return;
    }
    try {
      const constraint = clouddb.CloudDBZoneObjectOperatorConstraint.where(article).equalTo('id', id)
      await mCloudDBZone.executeBatchDeleteByCondition(constraint)
    } catch (error) {
      console.error(JSON.stringify(error))
    }
  }
}

module.exports = CloudDbUtils